/**
 * sybn version: 20250708
 */
var myChart;
var sybn_time = null;
var data_target_i = 0;
$(document).ready(function() {

    // 插入右上角展开/收起按钮
    $(".p_title").each(function() {
        var $panel_body = $(this).closest(".panel-heading ").next(".panel-body")
        if ($panel_body && $panel_body.hasClass("collapse")) {
            if ($panel_body.hasClass("in")) {
                // 收起按钮
                $(this).after("<span class=\"floatRight fa fa-chevron-down\" data-toggle=\"collapse\" data-target=\"\" title='缩放此面板'></span> <span class=\"floatLeft margin fa fa-compress\" title='全屏此面板 按ESC恢复'></span> <span class='floatLeft margin fa fa-caret-square-o-up' title='缩放输入框(按alt再点击可以超级加大)'></span>");
            } else {
                // 展开按钮
                $(this).after("<span class=\"floatRight fa fa-chevron-down collapsed\" data-toggle=\"collapse\" data-target=\"\" title='缩放此面板'></span> <span class=\"floatLeft margin fa fa-compress\" title='全屏此面板 按ESC恢复'></span> <span class='floatLeft margin fa fa-caret-square-o-up' title='缩放输入框(按alt再点击可以超级加大)'></span>");
            }
        }
    })

    // 处理特殊初始化
    $('body').on('click', '.init_collapse [data-toggle="collapse"]', function(e) {
        $(this).closest(".init_collapse").removeClass("init_collapse");
    });

    // 展开/收缩
    $('body').on('click', '.fa-caret-square-o-down', function(e) {
        $(this).removeClass("fa-caret-square-o-down").addClass("fa-caret-square-o-up");
        if (e.altKey) {
            $(this).closest(".panel").removeClass("sql_input_big").addClass("sql_input_big2");
        } else {
            $(this).closest(".panel").removeClass("sql_input_big").removeClass("sql_input_big2");
        }
    });
    $('body').on('click', '.fa-caret-square-o-up', function(e) {
        $(this).removeClass("fa-caret-square-o-up").addClass("fa-caret-square-o-down");
        if (e.altKey) {
            $(this).closest(".panel").removeClass("sql_input_big").addClass("sql_input_big2");
        } else {
            $(this).closest(".panel").addClass("sql_input_big");
        }
    });

    // 插入data-target
    $("[data-toggle][data-target='']").each(function() {
        data_target_i++;
        $(this).attr("data-target", "#data-target_"+data_target_i);
        $(this).parent().next().attr("id", "data-target_"+data_target_i);
    });
    // 插入访问按钮
    $(".show_openApi").append("<span class=\"closeApi input-group-addon submit\" style=\"display: none;\">×</span><span class=\"openApi input-group-addon submit\">访问</span><span class=\"openXls input-group-addon\">导出</span>");
    $(".show_openApi2").append("<span class=\"openApi input-group-addon submit\">访问</span>");

    // 注册回车事件
    $("input[name=url]").keydown(function() {
        if (event.keyCode == "13") {//keyCode=13是回车键
            $(this).parent().find('.openApi.submit').click();
        }
    });

    // 查询
    $('body').on('click', '.openApi', function(e) {
        var src = $(this).parent().find('[name=url]').val();
        if (src.indexOf(".json") > 0) {
            openApi(this, e)
        } else {
            window.open(src);
        }
    });

    // 导出
    $('body').on('click', '.openXls', function(e) {
        var src = $(this).parent().find('[name=url]').val();
        window.open(src.replace(".json", ".xls"));
    });
    // 新窗口查询
    $('body').on('dblclick', '.openApi', function(e) {
        clearTimeout(sybn_time);
        var src = $(this).parent().find('[name=url]').val();
        window.open(src);
    });
    $('body').on('click', '.updateApi', function(e) {
        var $p1 = $(this).parent();
        var $p2 = $p1.parent();
        if ($p1.length == 0) {
         $p1 = $clickthis.closest(".sybn-api-demo");
         $p2 = $p1;
        }
        var src = $p1.find('[name=url]').val();
        var formData = new FormData();
        var name = $("input").val();
        formData.append("file",$p1.find('[name=file]')[0].files[0]);
        resetPreviewTabs($p2);
        var aj = $.ajax({
                url : src,
                type : 'post',
                data : formData,
                cache: false,
                processData: false,
                contentType: false,
                success : function(data) {
                    //格式化json
                    var $jsonView = $p2.find('.json_view');
                    var rowsLength = data && data.rows ? data.rows.length : 0;
                    if (data && (!data.rows || data.rows.length <= 500)) {
                        // 如果返回值在500行以内，将json格式化显示
                        $jsonView.JSONView(data);
                    } else {
                        var jsonData = JSON.stringify(data);
                        $jsonView.text(jsonData);
                    }
                },
                error : function(data) {
                    alert((data.status > 401 && data.status < 499) ? "登录失效,或权限不足!" : "异常！" + data.status);
                    if (myChart) {
                        myChart.hideLoading();
                    }
                }
        });
    });

    // 关闭预览
    $('.closeApi').hide();
    $('body').on('click', '.closeApi', function() {
        var $p2 = $(this).parent().parent();
        $p2.find('iframe').hide();
        $p2.find('.iframe_preview').remove();
        $p2.find('.json_view').remove();
        $p2.find('.closeApi').hide();
    });

    $('body').on('change', '#data_select', function() {
        var selected = $(this).children('option:selected');
        setSelectField(selected);
        refreshApiUrl($(this).closest(".panel"));
    });
    $('body').on('change', '.refreshApiUrl', function() {
        refreshApiUrl($(this).closest(".panel"));
    });

    $('body').find().on("click", ".tablesorter", function() {
        $(".sybn_compare_diff").removeClass("sybn_compare_diff");
        $(".sybn_compare_highlight").remove();
    });

    if ($('#field_select').length>0) {
        $('#field_select').selectpicker({'selectedText' : 'cat'});
        $("#block_datalist").collapse('hide');
        $("#block_source").collapse('hide');
        $("#block_fill").collapse('hide');
        $("#block_indexs_new").collapse('hide');
    }

    $('body').on('change', '[name=view_type]', function(e) {
        var value = $(this).val();
        $(this).parent().parent().find(".view_param").empty().append($(".view_param_"+value).clone().children());
    });

    // 高亮指定列中的重复值
    $(document).on('click', '#title_btn_highlight_col', function () {
        var $this = $(this);
        var field = $("#title_copy_field").text(); // 获取当前列名
        var $table = $(".sybn_result_compare .iframe_preview > table"); // 表格选择器

        if (field && $table.length > 0) {
            highlightDuplicateValuesInColumn($table, [field]); // 使用已有的方法
        } else {
            alert("未找到对应的表格或字段");
        }
    });
});

function openApi(thiz, e, url, data) {
    var $clickthis = $(thiz);
    var $p1 = $clickthis.closest(".input-group");
    var $p2 = $p1.parent();
    if ($p1.length == 0) {
     $p1 = $clickthis.closest(".sybn-api-demo");
     $p2 = $p1;
    }
    var src = url || $p1.find('[name=url]').val();

    // 附加参数
    if ($p2.find('[name].append_post_value').length > 0) {
       if (data == null || data == undefined) {
          data = {};
       }
       $p2.find('[name].append_post_value').each(function(index,value){
          data[$(this).attr("name")]=$(this).val();
       });
   }

    // 防止双击事件触发单击事件
    clearTimeout(sybn_time);
    sybn_time = setTimeout(function() {
        $p1.find('.closeApi').show();
        openApiAction3(thiz, $p2, src, data);
    }, 300);
}

/**
 * 执行并将数据写入数据预览区
 * @param thiz 按钮 this
 * @param $p2 数据预览区父元素
 * @param src 需要请求的接口src
 * @param postData 参数
 */
function openApiAction3(thiz, $p2, src, postData) {
    var $clickthis = $(thiz);
    // 保存预览区旧的视图参数
    var $view_param = null;
    if ($p2.find(".view_param").length == 1) {
        $view_param = $p2.find(".view_param");
    }
    // 清空预览区
    resetPreviewTabs($p2);
    var statusKey = getQueryString("statusKey", null, src);
    var this_interval;
    if (statusKey) {
        // 开始在状态栏更新任务进度
        this_interval = refreshSelectMessage(statusKey, $p2, 3000);
    }
    var requestMethod = postData ? 'post' : 'get';
    var startTime = new Date().getTime();
    var aj = $.ajax({
        url : src,
        type : requestMethod,
        data : postData,
        dataType : 'json',
        success : function(data) {
            var endTime = new Date().getTime();

            if ($p2.data("this_interval")) {
                // 清理旧的 interval
                clearInterval($p2.data("this_interval"));
                $p2.data("this_interval", null)
            }
            var view_id = setPreviewTabs($p2);

            //格式化json
            var $jsonView = $p2.find('.json_view');
            var rowsLength = data && data.rows ? data.rows.length : 0;
            if (data && (!data.rows || data.rows.length <= 500)) {
                var jsonData = JSON.stringify(data);
                if (jsonData.length < 50000) {
                  // 如果返回值在500行以内, 且小于50KB，将json格式化显示
                  $jsonView.JSONView(data);
                } else {
                  // 如果返回值大于50KB，不格式化返回值，因为格式化太大json会卡死浏览器
                  $jsonView.text(jsonData);
                  $jsonView.prepend("<div style='color:#900b09; border:1px dotted #900b09; background:#FEB;'>返回内容过大，为了防止浏览器崩溃，已禁用json格式化。</div>");
                }
            } else if (data && data.rows.length > 100 && Object.keys(data.rows).length >= 30) {
                // 如果返回值在100行以上且列很多，不格式化返回值, 并仅保留最多300行来渲染json和table
                data.rows.splice(100, data.rows.length - 100);
                var jsonData = JSON.stringify(data);
                $jsonView.text(jsonData);
                $jsonView.prepend("<div style='color:#900b09; border:1px dotted #900b09; background:#FEB;'>返回内容过大["+rowsLength+"行]，为了防止浏览器崩溃，已禁用json格式化, 并仅保留前"+data.rows.length+"行。</div>");
            } else if (data && data.rows.length > 500) {
                // 如果返回值在500行以上，不格式化返回值, 并仅保留最多1000行来渲染json和table
                data.rows.splice(500, data.rows.length - 500);
                var jsonData = JSON.stringify(data);
                $jsonView.text(jsonData);
                $jsonView.prepend("<div style='color:#900b09; border:1px dotted #900b09; background:#FEB;'>返回内容过大["+rowsLength+"行]，为了防止浏览器崩溃，已禁用json格式化, 并仅保留前"+data.rows.length+"行。</div>");
            } else{
                // 如果返回值在500行以上，不格式化返回值，因为格式化太大json会卡死浏览器
                var jsonData = JSON.stringify(data);
                $jsonView.text(jsonData);
                $jsonView.prepend("<div style='color:#900b09; border:1px dotted #900b09; background:#FEB;'>返回内容过大["+rowsLength+"行]，为了防止浏览器崩溃，已禁用json格式化。</div>");
            }

            // 显示返回值
            if (!$clickthis.hasClass("hidetable")) {
                // ***** 渲染表格 *****
                if (src.indexOf(".json") > 0) {
                    // class=fixed
                    var $iframe_preview = $("<div id='view_table_"+view_id+"' class='iframe_preview tab-pane'><table class='table table-condensed tableTarget table-striped table-bordered table-hover margin0 tablesorter tablesorter-default'><thead><tr class='info'><th>-</th></tr></thead><tbody class='trTarget max-height200'><tr><td class='prompt'>暂无数据</td></tr></tbody></table></div>");
                    $jsonView.after($iframe_preview);
                    showDatasByData(data, $iframe_preview, {currentSecMills: endTime-startTime, rowsLength: rowsLength});

                    // "attachment": {
                    //   "sheetData_2": [...],
                    //   "sheetData_3": [...],
                    //   "sheetConfig": {
                    //     "数据": "rows",
                    //     "按影院": "$.attachment.sheetData_2",
                    //     "按渠道": "$.attachment.sheetData_3"
                    //   }
                    // }
                    if (data.attachment && data.attachment.sheetConfig && Object.keys(data.attachment.sheetConfig).length > 1) {
                      var $view_div = $p2.find('.view_div');
                      var $view_char = $view_div.find('.tab_sql_char');
                      for (var sheetName in data.attachment.sheetConfig) {
                        var sheetKey = data.attachment.sheetConfig[sheetName];
                        if (sheetKey.startsWith('$.attachment.')) {
                          sheetKey = sheetKey.substring(13); // sheetData_2
                        }
                        if (data.attachment[sheetKey]) {
                          var $li = $('<li class=""><a href="#view_table_'+view_id+'_'+sheetKey+'" data-toggle="tab" aria-expanded="false" class="tab_view_table">table</a></li>');
                          $li.find('a').text(sheetName);
                          $view_char.after($li)
                          var $iframe_preview = $("<div id='view_table_"+view_id+"_"+sheetKey+"' class='iframe_preview tab-pane'><table class='table table-condensed tableTarget table-striped table-bordered table-hover margin0 tablesorter tablesorter-default'><thead><tr class='info'><th>-</th></tr></thead><tbody class='trTarget max-height200'><tr><td class='prompt'>暂无数据</td></tr></tbody></table></div>");
                          $jsonView.after($iframe_preview);
                          var sheetRows = data.attachment[sheetKey];
                          showDatasByRows(sheetRows, $iframe_preview, {onlyData: true});
                        }
                      }
                    }
                }

                // 图表
                showCharParam(data, $p2, view_id, $jsonView, $view_param);
            }
        },
        error : function(data) {
            if ($p2.data("this_interval")) {
                // 清理旧的 interval
                clearInterval($p2.data("this_interval"));
                $p2.data("this_interval", null)
            }
            alert((data.status > 401 && data.status < 499) ? "登录失效,或权限不足!" : "异常！" + data.status);
            if (myChart) {
                myChart.hideLoading();
            }
        }
    });
}

function showCharParam(data, $p2, view_id, $jsonView, $view_param) {
    var hide_view_param = getQueryString("hide_view_param");
    if (!hide_view_param || hide_view_param != "true") {
        $jsonView.after("<div id='view_chars_"+view_id+"' class='char_view tab-pane'></div></div>");

        // 继承 view_param_map 中的可视化参数
        $p2.find("#view_chars_" + view_id).load("html/view_chars.html", function(){
            $p2.find(".view_param").append($(".view_param_1").clone().children());
            var view_param_map = $p2.data("view_param_map");
            if (view_param_map) {
                resetViewParam($p2.find(".view_param"), view_param_map);
                $p2.find(".view_param_select").hide();
            } else {
                var view_param_json = getQueryString("view_param_map");
                if (view_param_json) {
                    view_param_map = JSON.parse(view_param_json);
                    resetViewParam($p2.find(".view_param"), view_param_map);
                    $p2.find(".view_param_select").hide();
                }
            }
            if ($view_param) {
                // 继承原有的可视化参数
                var $view_param2 = $p2.find(".view_param");
                $view_param2.before($view_param);
                $view_param2.remove();
            }
        });
        if (data && data.rows && data.rows.length > 2) {
            $p2.on('click', '.auto_param', function(e) {
                autoSetParam(data, $p2);
            });
        }
    } else {
        // 隐藏 echarts
        $(".tab_sql_char").hide();
    }
}
/**
 * 自动分析维度度量字段(实验性功能)
 */
function autoSetParam(data, $p2) {
    var data1 = data.rows[0], data2 = data.rows[1];
    var regexDateTime = /^(?:19|20)[0-9][0-9]-(?:(?:0[1-9])|(?:1[0-2]))-(?:(?:[0-2][1-9])|(?:[1-3][0-1])) (?:(?:[0-2][0-3])|(?:[0-1][0-9])):[0-5][0-9]:[0-5][0-9]$/;
    var regexDate = /^(?:19|20)[0-9][0-9]-(?:(?:0[1-9])|(?:1[0-2]))-(?:(?:[0-2][1-9])|(?:[1-3][0-1]))$/;

    var dim = []; // 维度, 比如: 时间, 性别
    var metric = []; // 度量, 必须是数字, 比如: 金额, 人数
    var xField = "";
    var intervalMin = true, intervalHour = true, intervalDay = true;
    var minDate = null, maxDate = null;
    for (var field in data1) {
        var v = data1[field];
        if (typeof v == 'number') {
            metric.push(field);
        } else {
            dim.push(field);
            if (typeof v == 'string' && regexDateTime.test(v) && regexDateTime.test(data2[field])) {
                xField = field;
            } else if (typeof v =='string' && regexDate.test(v) && regexDate.test(data2[field])) {
                xField = field;
            }
        }
    }
    var timeScope = 0;
    if (xField) {
        for (var idx in data.rows) {
            var v = data.rows[idx][xField];
            if (!v.endsWith(":00")) {
                intervalMin = false;
            } else if (!v.endsWith(":00:00")) {
                intervalHour = false;
            } else if (!v.endsWith("00:00:00")) {
                intervalDay = false;
            }
            minDate = (minDate == null || minDate > v) ? v : minDate;
            maxDate = (maxDate == null || maxDate < v) ? v : maxDate;
        }
        timeScope = new Date(maxDate).getTime() - new Date(minDate).getTime();
    }
    var interval = "1DAY";
    if (!intervalDay && intervalHour && intervalMin && timeScope < 86400000*32) {
        interval = "3600sec";
    } else if (!intervalDay && !intervalHour && intervalMin && timeScope < 86400000*14) {
        interval = "60sec";
    } else if (!intervalDay && !intervalHour && !intervalMin && timeScope < 86400000) {
        interval = "1sec";
    }
    if (xField != "" && metric.length > 0) {
        $p2.find(".view_param").find("[name=xField]").val(xField);
        $p2.find(".view_param").find("[name=xScope]").val('');
        $p2.find(".view_param").find("[name=xConver]").val('date');
        $p2.find(".view_param").find("[name=interval]").val(interval);
        $p2.find(".view_param").find("[name=aggFields]").val(metric.toString());
        $p2.find(".view_param").find("[name=groupKeys]").val(dim.toString());
    }
}

/**
 * 显示任务进度
 */
function refreshSelectMessage(statusKey, $p2, delay, name, onComplete) {
    delay = delay || 1000;
    var $jsonView = $p2.find('.json_view');
    var r = {
        statusKey:statusKey,
        p:$p2,
        jsonView:$jsonView,
        delay:delay,
        count:0,
        textPlan:true,
        add: function() {return this.count++},
        sub: function() {return this.count--}
    };

    if ($p2.data("this_interval")) {
        // 清理旧的 interval
        clearInterval($p2.data("this_interval"));
        $p2.data("this_interval", null)
    }
    var return_interval = setInterval(function() {
        if (r.count > 0) {
            return;
        }
        $.ajax({
            url : "api/job_v2/jobStatus.json?statusKey=" + r.statusKey+ "&r=" + r.add(),
            type : "get",
            dataType : "json",
            success : function(res) {
               // 检查元素是否仍然存在
                if (!r.jsonView.closest('body').length) {
                    // 元素已不存在，清理定时器
                    clearInterval(r.return_interval);
                    console.log("目标元素已不存在，停止定时任务");
                    return;
                }
                if (res && res.job && res.job.completionRate) {
                    job = res.job;
                    var t1a = "<span style='color:blue'>计算中,请稍后...</span><br/>";
                    var t1b = "<span style='color:blue'>计算中,请稍后......</span><br/>";
                    var t1c = "<span style='color:green'>计算完成, 开始下载数据!</span><br/>";
                    t1 = res.job.complete? t1c : (r.textPlan ? t1a : t1b);
                    r.textPlan = !r.textPlan;
                    var rate = job.completeTask + "/" + job.maxTask + " [" + job.completionRate + "]";
                    var t2 = res.job.currentTimeStr + " <b>" + (name ? name : "") + "任务进度:</b> <span style='color:red'>" + rate + "</span> ";
                    var t3 = detailLogToHtml(job.detailLog);
                    var deleteBtn = "<span class='close-api-result red' style='float:right; border:1px solid #F76; background-color:#FEE; line-height:1; cursor:pointer;' title='关闭此日志'>关闭日志</span>";
                    r.jsonView.html(deleteBtn + t2 + t1 + t3);

                    // 绑定删除按钮事件
                    r.jsonView.find('.close-api-result').on('click', function() {
                        console.log("手动关闭任务进度显示并注销定时任务" + r.return_interval);
                        clearInterval(r.return_interval);
                        r.jsonView.remove();
                    });

                    if (res.job.currentData){
                      r.jsonView.append("<div class='iframe_preview tab-pane'><table class='table table-condensed tableTarget table-striped table-bordered table-hover margin0 '><thead><tr class='info'><th>-</th></tr></thead><tbody class='trTarget max-height200'><tr><td class='prompt'>暂无数据</td></tr></tbody></table></div>");
                      var $iframe_preview = r.jsonView.find(".iframe_preview");
                      // 如果返回值在1000行以内，显示所有数据
                      showDatasByData(res.job.currentData, $iframe_preview);
                      $iframe_preview.prepend("<div style='color: #900b09;border: 1px dotted #900b09;background: #FEB;'>sql 尚未查询结束, 以下为数据预览:</div>");
                    }
                    if(res.job.completionRate == '100%' && res.job.complete && new Date().getTime() - new Date(res.job.heartTime).getTime() > 40000) {
                        clearInterval(r.return_interval);
                        console.log("任务完成, 停止刷新任务进度:" + r.return_interval);
                    }
                }
                r.sub();
            },
            error : function(data) {
                if (r && r.return_interval) {
                    clearInterval(r.return_interval);
                    console.log("停止刷新任务进度:" + r.return_interval);
                }
                if (data && data.status) {
                  alert((data.status > 401 && data.status < 499) ? "登录失效,或权限不足!" : "异常！" + data.status);
                }
                r.sub();
            }
        });
    }, delay);
    $p2.data("this_interval", return_interval);
    r.return_interval = return_interval;
    console.log("开始刷新任务进度:" + r.return_interval);
    return return_interval;
}

function resetViewParam ($p, param){
    if (param.view_type) {
        $(this).parent().parent().find(".view_param").empty().append($(".view_param_"+param.view_type).clone().children());
    }
    $p.find('[name=xField]').val(param.xField);
    $p.find('[name=xValues]').val(param.xValues);
    $p.find('[name=xScope]').val(param.xScope);
    $p.find('[name=xConver]').val(param.xConver);
    $p.find('[name=aggFields]').val(param.aggFields);
    $p.find('[name=groupKeys]').val(param.groupKeys);
    $p.find('[name=interval]').val(param.interval);
    $p.find('[name=defaults]').val(param.defaults);
}

/**
 * 初始化数据预览区
 * @param $parent
 * @returns
 */
function resetPreviewTabs($parent) {
    initViewCharsParam();

    $parent.find('.view_div').remove();
    $parent.find('.json_view').remove();
    $parent.find(".iframe_preview").remove();

    $parent.append("<div class='view_div bgfff'></div>")
    var view_div = $parent.find('.view_div');
    view_div.append("<div class='json_view'><b>loading ...</div></div>")
    var $jsonView = $parent.find('.json_view');
    view_div.find('.closeApi').hide();
}

/**
 * 显示下方数据预览区
 */
var view_num = 1;
function setPreviewTabs($parent, active) {

    var view_div = $parent.find('.view_div');

    var view_id = view_num++;
    var view_tabs_id = "view_tabs_" + view_id;
    var view_json_id = "view_json_" + view_id;
    var view_table_id = "view_table_" + view_id;
    var view_chars_id = "view_chars_" + view_id;

    view_div.find('.json_view').remove();
    var tabs_compress = '<li><a href="##"><span class="margin fa fa-compress">结果</span>:</a></li>';
    var tabs_json = '<li class="active"><a href="#view_json" data-toggle="tab" aria-expanded="false" class="tab_view_json">json</a></li>';
    var tabs_table = '<li class=""><a href="#view_table" data-toggle="tab" aria-expanded="false" class="tab_view_table">table</a></li>';
    var tabs_chars = '<li class="tab_sql_char"><a href="#view_chars" data-toggle="tab" aria-expanded="false" class="tab_view_chars">chars</a></li>';
    var tabs_clear =
    '<li class="tab_clear" style="float:right"><a href="##" onClick="$(this).closest(\'.view_div\').remove()">清空</a></li>'
    +'<li class="tab_clear" style="float:right"><a class="tab_rows" href="##" ></a></li>';
    var tabs = '<ul id="view_tabs" class="nav nav-tabs">'+tabs_compress+tabs_json+tabs_table+tabs_chars+tabs_clear+'</ul>'
    tabs = tabs.replace("view_json",view_json_id).replace("view_table",view_table_id).replace("view_chars",view_chars_id);

    view_div.append(tabs);
    view_div.append("<div class='tab-content'></div>");
    var $tab_content = view_div.find('.tab-content');

    $tab_content.append("<div id='"+view_json_id+"' class='json_view tab-pane active'>loading ...</div></div>");

    if (active && active == "showChars") {
        $tab_content.append("<div id='"+view_chars_id+"' class='char_view tab-pane'></div></div>");
        $tab_content.find("#" + view_chars_id).load("html/view_chars.html", function(){
            $tab_content.find(".view_param").append($(".view_param_1").clone().children());
        });
    }
    return view_id;
}


var init_view_chars_param = false;
function initViewCharsParam(){
    if (init_view_chars_param){
        return;
    }
    init_view_chars_param= true;
    $("body").append("<div id='view_chars_param'></div>");
    $("#view_chars_param").load("html/view_chars_param.html");
}

function setSelectField(selected) {
    var fields = $(selected).data("field");
    $("#field_select").empty();
    if (fields) {
        var fieldList = fields.split(","); // 字符分割
        for (var i = 0; i < fieldList.length; i++) {
            var field_option = $("<option value='" + fieldList[i] + "'>" + fieldList[i] + "</option>");
            $('#field_select').append(field_option);
        }
    }
    $('#field_select').selectpicker('refresh');
}

function refreshApiUrl(input) {
    var $url = $(input).find("[name=url]");
    var url = $url.val();
    $(input).find("[name][name!=url]").each(
        function() {
            var name = $(this).attr("name");
            var value = $(this).val();
            if (url.indexOf(name + "=") > 0) {
                var reg = new RegExp("" + name + "=[^&]*");
                if (name == "groupBys" && value == "") {
                    url = url.replace(reg, "").replace("&&", "&").replace(/&$/, "");
                } else if (name == "field" && (!value || value == "")) {
                    url = url.replace(reg, "").replace("&&", "&").replace(/&$/, "");
                } else {
                    url = url.replace(reg, name + "=" + value);
                }
            } else if (value && value != "") {
                url += "&" + name + "=" + value;
            }
        });
    $url.val(url);
}

var showCharts = function(url, $div, type) {
    myChart = echarts.init($div[0]);
    myChart.showLoading(loadConf);
    var aj = $.ajax({
        url : url,
        type : 'get',
        dataType : 'json',
        success : function(data) {
            showChartsByData(data, $div, type);
        },
        error : function(data) {
            alert((data.status > 401 && data.status < 499) ? "登录失效,或权限不足!" : "异常！" + data.status);
            if (myChart) {
                myChart.hideLoading();
            }
        }
    });
};

var showChartsByData = function(data, $div, type) {
    myChart = echarts.init($div[0]);
    if (data.result == true && data.rows && data.rows.length > 0) {
        loadOption(data, type);
    } else {
        if (myChart) {
            myChart.hideLoading();
        }
    }
}

var showDatas = function(url, $div) {
    $div.find('.prompt').text('载入中...');
    var startTime = new Date().getTime();
    var aj = $.ajax({url : url, type : 'get', dataType : 'json',
        success : function(data) {
            showDatasByData(data, $div, {currentSecMills: new Date().getTime()-startTime});
        },
        error : function(data) {
            alert((data.status > 401 && data.status < 499) ? "登录失效,或权限不足!" : "异常！" + data.status);
            $div.find('.prompt').text(dateFormatting(new Date(), "yyyy-MM-dd hh:mm:ss") + ' 载入失败,请稍后重试!');
        }
    });
}

/** 渲染返回值 **/
var showDatasByData = function(data, $div, op, filename) {
    var currentSecMills = null;
    var rowsLength = null;
    if (op && typeof(op) == 'object') {
      // 新版使用 op 对象 传参
      currentSecMills = op.currentSecMills || null;
      filename        = op.filename        || null;
      rowsLength      = op.rowsLength      || null;
      onlyData        = op.onlyData        || false;
    } else if (op && typeof(op) == 'string' && !filename) {
      filename = op;
    } else if (op && typeof(op) == 'number') {
      currentSecMills = op;
    }

    $view_div = $div.closest('.view_div');
    $view_div.find('.tab_rows').text('');
    $(".sybn_compare_diff").removeClass("sybn_compare_diff");
    $(".sybn_compare_highlight").remove();
    $(".sybn_compare_link").text("对比表格");
    if (data && data.result == true) {
        if (data.rows && data.rows.length > 0) {

            // 渲染表格
            loadDataToTable(data.rows, $div, "#defaultsTemplate");

            // 开启表头排序
            $div.find(".tablesorter").tablesorter();
            $div.find(".tablesorter").on("sortEnd", function() {
                compareTableData($div, $view_div);
            });

            $view_div.find('.tab_view_table').click();

            // 显示提示信息
            var rowPrompt = "";
            if (currentSecMills) {
                rowPrompt += (currentSecMills > 100000 ? (currentSecMills / 1000).toFixed(0) + "秒 " : (currentSecMills / 1000).toFixed(2) + "秒 ");
            }
            rowPrompt += rowsLength && rowsLength != data.rows.length ? "返回[" + rowsLength + "]条结果,只显示前" + data.rows.length + "条" : "返回[" + data.rows.length + "]条结果 ";
            var $tab_rows = $view_div.find('.tab_rows')
            $tab_rows.text(rowPrompt);

            $tab_rows.off('click');
            if (data.shortSqlUrl) {
                $tab_rows.on('click', function(){copyToClipboardStr(data.shortSqlUrl)});
            }

            compareTableData($div, $view_div);

            if (data.rows.length <= 1000) {
                // 导出数据  为 csv 文件
                var csvDownload = $("<a href='###' title='直接导出以下表格的数据到csv文件' >导出表格</a>")
                csvDownload.on("click", function(){downloadJson2Csv(data.rows, filename)});
                var csvDownloadLi = $("<li class='tab_clear' style='float:right'></li>")
                csvDownloadLi.append(csvDownload);
                $view_div.find('.tab_rows').closest('li').before(csvDownloadLi);

                // 复制到粘贴板
                var tsvDownload = $("<a href='###' title='复制以下表格的数据到粘贴板' >复制到粘贴板</a>")
                tsvDownload.on("click", function(){downloadJson2Tsv(data.rows)});
                var tsvDownloadLi = $("<li class='tab_clear' style='float:right'></li>")
                tsvDownloadLi.append(tsvDownload);
                $view_div.find('.tab_rows').closest('li').before(tsvDownloadLi);
            }

            var tableFixed = $("<a href='###' title='对齐列宽' >对齐列宽</a>")
            tableFixed.on("click", function(){
                $table = $view_div.find('table');
                if ($table.hasClass("tableFixed")) {
                    $table.removeClass("tableFixed");
                    $(this).removeClass("active");
                } else {
                    $table.addClass("tableFixed");
                    $(this).addClass("active");
                }
            });
            var tableFixedLi = $("<li class='tab_tableFixed' style='float:right'></li>")
            tableFixedLi.append(tableFixed);

            if (data.rows.length > 1000) {
                $dev.prepend("<div style='color: #900b09;border: 1px dotted #900b09;background: #FEB;'>返回值内容过大["+rowsLength+"行]，为了防止浏览器崩溃，只显示前1000条数据，如需导出大量数据，建议直接导出csv。</div>");
            }
            $view_div.find('.tab_rows').closest('li').before(tableFixedLi);

        } else {
            $div.find('.prompt').text('没有查询到数据!');
        }
    } else if (data.result == false && data.msg == "-100") {
        $div.find('.prompt').text('请先登录!');
    } else if (data.result == false && !data.msg) {
        $div.find('.prompt').html(dateFormatting(new Date(), "yyyy-MM-dd hh:mm:ss") + ' 载入失败,请稍后重试!');
    } else {
        $div.find('.prompt').html(dateFormatting(new Date(), "yyyy-MM-dd hh:mm:ss") + ' 载入失败,请稍后重试!');
        if (data && data.msg) {
            $div.find('.prompt').append('<a style="display:none" href="###" onclick="$(this).hide();$(this).next().show();$(this).next().next().show()">显示详情</a>')
            $div.find('.prompt').append('<a href="###" onclick="$(this).hide();$(this).next().hide();$(this).prev().show()">隐藏详情</a>')
            $div.find('.prompt').append('<p style="color: green;white-space: pre-wrap;">' + data.msg.replace(/\r?\n/g,"<br>") + '</p>')
        }
        $view_div.find('.tab_view_table').click();
    }
}


/** 渲染返回值 **/
var showDatasByRows = function(rows, $div, op) {
    if (rows && rows.length > 0) {
        if (rows.length > 100) {
            rows = rows.slice(0, 100); // 使用 slice 避免修改原始数组
            $div.prepend("<div style='color: #900b09;border: 1px dotted #900b09;background: #FEB;'>以下数据已限制为仅显示前 100 行, 导出excel时可完整显示</div>");
        }

        // 渲染表格
        loadDataToTable(rows, $div, "#defaultsTemplate");

        // 开启表头排序
        $div.find(".tablesorter").tablesorter();
    }
}

// 对比2个 table 的差异
var compareTableData = function($div, $view_div) {
    $(".sybn_compare_diff").removeClass("sybn_compare_diff");
    $view_div.find(".sybn_compare_highlight, .sybn_compare_link").remove();
    $(".sybn_compare_link").text("对比表格");
    $(".sybn_compare_highlight").text("高亮差异");

    if ($div.closest(".sybn_result_compare").length > 0) {
        // 对比数据并显示 tsv 对比链接
        var tsvCompare = $("<a href='###' title='对比2个表格的数据' class='sybn_compare_link'>对比表格</a>");
        var highlightCompare = null;
        var tables = $(".sybn_result_compare .iframe_preview>table");
        if (tables.length == 2) {
            var lText = tables[0].innerText, rText = tables[1].innerText;
            if (lText == rText) {
                $(".sybn_compare_link").text("数据一致!");
                tsvCompare = $("<a href='###' title='对比2个表格的数据' class='sybn_compare_link'>数据一致!</a>");
            } else {
                highlightCompare = $("<a href='###' title='高亮2个表格的数据' class='sybn_compare_highlight'>高亮差异</a>");
            }
        }
        tsvCompare.on("click", function(){
            var tables = $(".sybn_result_compare .iframe_preview>table");
            if (tables.length != 2) {
                console.log("没有可对比数据!");
                $(".sybn_compare_link").text("对比表格");
            } else {
                var lText = tables.eq(0).find("thead th").map(function() {return this.innerText.trim()}).get().join('\t') + "\n" + tables.eq(0).find("tbody")[0].innerText;
                var rText = tables.eq(1).find("thead th").map(function() {return this.innerText.trim()}).get().join('\t') + "\n" + tables.eq(1).find("tbody")[0].innerText;

                // TODO
//                var ct1 = tables.eq(1).clone();
//                ct1.find('tbody tr td, tbody tr th').map(function() {return $(this).text($(this).text().replace(/\t|\n/g, ' '));})
//                var lText2 = ct1[0].innerText;


//                var lzip = zip(lText), rzip = zip(rText);
                var param = "l=" + encodeURIComponent(lText) + "&r=" + encodeURIComponent(rText);
                var pzip = zip(param);
                if (lText != rText) {
//                    window.open("./js/plugin/mergely/examples/simple.html?lzip="+lzip+"&rzip="+rzip);
                    window.open("./js/plugin/mergely/examples/simple.html?wrap_lines=false&z="+pzip);
                } else if ($(this).text() == "数据一致!") {
//                    window.open("./js/plugin/mergely/examples/simple.html?lzip="+lzip+"&rzip="+rzip);
                    window.open("./js/plugin/mergely/examples/simple.html?wrap_lines=false&z="+pzip);
                } else {
                    $(".sybn_compare_link").text("数据一致!");
                }
            }
        });
        var tsvCompareLi = $("<li class='tab_clear' style='float:right'></li>")
        tsvCompareLi.append(tsvCompare);
        $view_div.find('.tab_rows').closest('li').before(tsvCompareLi);

        // 根据行列位置 在 table 中高亮差异数据
        if (highlightCompare != null && tables.length == 2) {

            var highlightCompareLi = $("<li class='tab_clear' style='float:right'></li>")
            highlightCompareLi.append(highlightCompare);
            $view_div.find('.tab_rows').closest('li').before(highlightCompareLi);

            highlightCompare.on("click", function(){
                var diffCount = 0;
                var tables = $(".sybn_result_compare .iframe_preview>table");
                var lt = tables.eq(0), rt = tables.eq(1);
                if (lt.find('th').length != rt.find('th').length) {
                    alert("2个表格的列数不一致!");
                    return;
                }
                var l_tr_list = lt.find('tr'), r_tr_list = rt.find('tr');
                for (var i = 0; i < l_tr_list.length && i < r_tr_list.length; i++) {
                    var l_tr = l_tr_list.eq(i).find('td'), r_tr = r_tr_list.eq(i).find('td');
                    for (var j = 0; j < l_tr.length && j < r_tr.length; j++) {
                        if (l_tr[j].innerText != r_tr[j].innerText) {
                            l_tr.eq(j).addClass('sybn_compare_diff');
                            r_tr.eq(j).addClass('sybn_compare_diff');
                            diffCount++;
                        }
                    }
                }

                $(".sybn_compare_highlight").text(diffCount +"个值差异" + (l_tr_list.length == r_tr_list.length ? '' : " " + Math.abs(l_tr_list.length - r_tr_list.length) + "行差异"));
            });
        }
    }
}

/**
 * 高亮指定列中的重复值
 * @param {string} tableSelector - 表格选择器
 * @param {Array<string>} columnNames - 需要检查的列名列表
 */
function highlightDuplicateValuesInColumn(tableSelector, columnNames) {
    $(".sybn_compare_diff").removeClass("sybn_compare_diff");
    $(tableSelector).each(function () {
        var $table = $(this);
        var $headers = $table.find("thead th");
        var $rows = $table.find("tbody tr");

        // 1. 找到需要检查的列索引
        var colIndices = [];
        columnNames.forEach(function (colName) {
            $headers.each(function (index) {
                if ($(this).text().trim() === colName.trim()) {
                    colIndices.push(index);
                }
            });
        });

        if (colIndices.length === 0) return;

        // 2. 收集每列的值及其出现次数
        var valueCounts = {};
        colIndices.forEach(function (colIndex) {
            valueCounts[colIndex] = {};
            $rows.each(function () {
                var cellText = $(this).find("td").eq(colIndex).text().trim();
                if (!valueCounts[colIndex][cellText]) {
                    valueCounts[colIndex][cellText] = 0;
                }
                valueCounts[colIndex][cellText]++;
            });
        });

        // 3. 高亮重复值
        $rows.each(function () {
            var $row = $(this);
            colIndices.forEach(function (colIndex) {
                var $cell = $row.find("td").eq(colIndex);
                var cellText = $cell.text().trim();

                if (valueCounts[colIndex][cellText] > 1) {
                    $cell.addClass("sybn_compare_diff"); // 添加自定义 class
                }
            });
        });
    });
}

/**
 * 组装视图参数
 **/
function getViewParam($p){
    var chartsType = $p.find('[name=result_view_charts_type]').val();
    var xField = ($p.find('[name=xField]').val() || "").replace(/'/g, "");
    var xValues = ($p.find('[name=xValues]').val() || "").replace(/'/g, "");
    var xScope = ($p.find('[name=xScope]').val() || "").replace(/'/g, "");
    var xConver = ($p.find('[name=xConver]').val() || "").replace(/'/g, "");
    var aggFields = ($p.find('[name=aggFields]').val() || "").replace(/'/g, "");
    var groupKeys = ($p.find('[name=groupKeys]').val() || "").replace(/'/g, "");
    var interval = ($p.find('[name=interval]').val() || "").replace(/'/g, "");
    var defaults = ($p.find('[name=defaults]').val() || "").replace(/'/g, "");

    var view_param_map = {
        view_type:  $('[name=view_type]').val(),
        chartsType: chartsType,
        xField:     xField,
        xValues:    xValues,
        xScope:     xScope,
        xConver:    xConver,
        aggFields:  aggFields,
        groupKeys:  groupKeys,
        interval:   interval,
        defaults:   defaults
    };

    console.log(JSON.stringify(view_param_map));

    var result_view_fun_name = $p.find('[name=result_view_fun_name]').val();
    var result_view_fun;
    if (result_view_fun_name == "to_scope_list") {
        result_view_fun = "to_scope_list('"+xField+"', '"+xScope+"', '"+xConver+"', '"+aggFields+"', '"+groupKeys+"', '"+interval+"', '"+defaults+"')"
    } else if (result_view_fun_name == "to_pie_list") {
        result_view_fun = "to_pie_list('"+xField+"', '"+xValues+"', '"+aggFields+"', '"+groupKeys+"', '"+defaults+"')"
    }
    $p.find(".result_view_fun").text(result_view_fun);
    return result_view_fun;
}

/**
 * detailLog
 **/
function detailLogToHtml(detailLog){
    if (!job.detailLog) {
        return ""
    }
    var res = "";
    for (var i in detailLog) {
        res += !detailLog[i] ? "" : "<span style='color:#777'>" + detailLog[i].replace(/\r?\n/g,"<br/>") + "</span><br/>";
    }
    return res;
}
/**
 * 注销
 **/
function loginOut (url, callback) {
    if (!url){
        alert("注销成功!");
        callback();
        return;
    }
    var aj = $.ajax({
        url : url,
        type : 'post',
        data : {},
        cache : false,
        dataType : 'json',
        success : function(data) { callback(data); },
        error : function(data) { alert("注销失败!"); }
    });
}

/**
 * 登陆
 **/
function loginFrom (url, callback) {
    var username = $("[name=username]").val(), password = $("[name=password]").val();
    if (!username) {
        $('#loginModal .prompt').html('<span>请输入帐户名 </span>');
        return;
    } else if (!(/^[a-zA-Z][a-zA-Z0-9_]{3,15}$/.test(username))){
        $('#loginModal .prompt').html('<span>帐户名不合法 </span>');
        return;
    }
    $('[aria-describedby]').popover('hide');
    $('div.popover').remove();

    $("[name=password]").val("");
    if (!url){
        $('#loginModal .prompt').html('<span>登录成功</span>');
        $('#loginModal').modal('hide');
        callback({username:username});
        return;
    }
    $('#loginModal .prompt').html('<span>登录中...</span>');
    var aj = $.ajax({
      url : url,
      type : 'post',
      data : { username : username, password : $.md5(password) },
      cache : false,
      dataType : 'json',
      success : function(data) {
        $(".login_submit").button('reset')
        if (data.result || data.code == 200) {
          $('#loginModal .prompt').html('<span>登录成功</span>');
          $('#loginModal').modal('hide');
          callback(data);
        } else {
          $('#loginModal .prompt').html('<span>账户或密码不正确</span>');
        }
      },
      error : function(data) {
        $(".login_submit").button('reset');
        $('#loginModal .prompt').html('<span>服务器繁忙，稍后重试</span>');
      }
    });
  }

$(document).ready(function(){
    if ($("#sub-menu").length == 0) {
        return;
    }

    // 开启粘贴板, 复制 data-clipboard-target 对应的值
    new ClipboardJS('.copy_btn');

    $('#title-menu').hide();
    // 开启标题栏右键菜单
    $(".sybn_contextmenu").on("contextmenu", "th", function(e){
        $('#sub-menu').hide();
        $("#title-menu").show();

        var menuWidth = $("#title-menu").outerWidth(); // 获取菜单宽度
        var pageWidth = $(window).width(); // 页面宽度
        var leftPosition = (pageWidth - e.pageX < menuWidth) ? (pageWidth - menuWidth - 20) : e.pageX;
        $('#title-menu').css({'top': e.pageY + 'px', 'left': leftPosition + 'px'});

        var $this = $(this);

        var field = $this.data("field");
        $("#title_copy_field").text(field);

        var type = $this.data("type");
        $("#title_copy_type").text($this.data("type"));

        // 复制同列
        var column = $this.index();
        var $table = $this.closest(".table")
        var trs = $table[0].getElementsByTagName('tr');
        var total = 0, trNotEmptySize = 0;
        var colStr = field;
        var uniqueValues = new Set(); // 用于存储唯一值
        for(var i = 1; i < trs.length ; i++){
            var td=trs[i].getElementsByTagName('td')[column];
            var tdVal = td.innerText;
            var t = parseFloat(tdVal);
            if (t) total += t;
            colStr += "\r\n" + tdVal;
            if (tdVal != '') {
                trNotEmptySize ++;
                uniqueValues.add(tdVal); // 添加到 Set 中自动去重
            }
        }
        $("#title_copy_value").text(total);
        $("#title_copy_col").text(colStr);
        $("#title_copy_col_size").text("总计=" + trs.length + ",非空=" + trNotEmptySize + ",去重=" + uniqueValues.size);

        // 复制所有字段名
        var tds = $this.closest("tr")[0].getElementsByTagName('th');
        var fieldNameList = [];
        for(var i = 0; i < tds.length ; i++){
            fieldNameList.push(tds[i].innerText);
        }
        $("#title_copy_all_field").text(fieldNameList.join(", "));
        $("#title_copy_all_field_size").text(fieldNameList.length + "个值");

        return false;
    });

    $("#sub-menu").hide();
    // 开启td右键菜单
    $(".sybn_contextmenu").on("contextmenu", "td", function(e){
        var $this = $(this);
        var $input_group = $this.closest(".input-group, .sybn-api-demo");
        var editorId = $input_group.find('[name=url],[name=sql]').data("editor");

        $("#sub-menu .sql_append").data("editor_id", editorId);
        $('#title-menu').hide();
        $("#sub-menu").show();

        var menuWidth = $("#sub-menu").outerWidth(); // 获取菜单宽度
        var pageWidth = $(window).width(); // 页面宽度
        var leftPosition = e.pageX; // 默认左侧定位
        // 如果距离右侧不够显示菜单，则靠左显示
        if (pageWidth - e.pageX < menuWidth) {
            leftPosition = pageWidth - menuWidth - 20; // 留出10px边距
        }
        $('#sub-menu').css({'top': e.pageY + 'px', 'left': leftPosition + 'px'});

        var field = $this.data("field");
        $("#copy_field").text(field);
        $("#sub-menu .sql_append").data("field", field);

        var type = $this.data("type");
        $("#copy_type").text($this.data("type"));
        $("#sub-menu .sql_append").data("type", type);

        var value = unescapeHtmlAndReplaceBr($this.html());
        $("#copy_value").val(value);
        $("#sub-menu .sql_append").data("value", value);

        $("#copy_field_value").val(field + "='" + value+ "'");

        return false;
    });

    // 单击关闭右键菜单
    $(document).on('click', "#sub-menu textarea, #sub-menu input", function(e) {return false; });
    $(document).on('click', function(e) {
        var evt = event.srcElement ? event.srcElement : event.target;
        if (evt.id == 'sub-menu' || evt.id == 'title-menu') {
            return;
        }
        $('#sub-menu').hide();
        $('#title-menu').hide();
    });
});
